package com.syqc.login

import com.syqc.comlib.AppConfigs
import com.syqc.comlib.UserConstant
import com.syqc.comlib.entity.AppGpsColumn
import com.syqc.comlib.rx.LiveDataBus
import com.syqc.comlib.utils.AppContext
import com.syqc.comlib.utils.CacheMMKV
import com.syqc.comlib.utils.GsonUtil
import com.syqc.entity.GpsDetail
import com.syqc.entity.LocationInfo
import com.syqc.entity.LocationStatus
import com.syqc.entity.NameValue
import com.syqc.monitor.R
import com.syqc.utils.TimeUtil
import com.syqc.utils.Units
import org.json.JSONObject
import kotlin.concurrent.thread

/**
 *@Author pc_hfjs
 *@Date 2022/1/13 17:24
 *@Desc
 */
object LocationStatusModel {
    private val switchs = ArrayList<AppGpsColumn>()
    private val switchList = ArrayList<LocationStatus>()
    val changeList = ArrayList<AppGpsColumn>()

    fun initData() {
        val local = CacheMMKV.decodeString("AppGpsColumn")
        val info = AppConfigs.appGpsColumn ?: if (local.isEmpty()) {
            val default =
                "[{\"key\": \"drctCn\",\"switch\": 1}, {\"key\": \"accTime\",\"switch\": 1}, {\"key\": \"teamName\",\"switch\": 1}, {\"key\": \"driverStatic\",\"switch\": 0}, {\"key\": \"driverSign\",\"switch\": 0}, {\"key\": \"alarms\",\"switch\": 0}, {\"key\": \"addr\",\"switch\": 1}, {\"key\": \"st1\",\"switch\": 0}, {\"key\": \"st3\",\"switch\": 0}, {\"key\": \"st4\",\"switch\": 0}, {\"key\": \"st5\",\"switch\": 0}, {\"key\": \"st2\",\"switch\": 0}, {\"key\": \"carName\",\"switch\": 0}, {\"key\": \"satl\",\"switch\": 0}, {\"key\": \"sgn\",\"switch\": 0}, {\"key\": \"c3\",\"switch\": 0}, {\"key\": \"bd\",\"switch\": 0}, {\"key\": \"be\",\"switch\": 0}, {\"key\": \"appDoor1\",\"switch\": 0}, {\"key\": \"appDoor2\",\"switch\": 0}, {\"key\": \"appDoor3\",\"switch\": 0}, {\"key\": \"appDoor4\",\"switch\": 0}, {\"key\": \"appDoor5\",\"switch\": 0},{\"key\": \"todayRun\",\"switch\": 0},{\"key\": \"offlineDuration\",\"switch\": 0},{\"key\": \"mileLng\",\"switch\": 0},{\"key\": \"coiledDriving\",\"switch\": 0}]"
            GsonUtil.formArrayList(default, AppGpsColumn::class.java)
        } else {
            GsonUtil.formArrayList(local, AppGpsColumn::class.java)
        }
        //过滤设定的参数
//        val filter = info.filter { keys.contains(it.key) && !(it.key == "satl" || it.key == "sgn") }
        switchs.clear()

        switchs.addAll(info.filter { it.switch == 1 })
        changeList.clear()
        changeList.addAll(info)
    }

    fun update(data: MutableList<AppGpsColumn>) {
        changeList.clear()
        changeList.addAll(data)
        switchs.clear()
        switchs.addAll(changeList.filter { it.switch == 1 })
    }


    fun saveLocal() {
        val toJson = GsonUtil.toJson(changeList)
        CacheMMKV.encode("AppGpsColumn", toJson)
        LiveDataBus.get().with("upInfoState").postValue(true)
    }

    /**
     * 更新并返回数据
     */
    private fun getString(resId: Int): String {
        return AppContext.getDescById(resId)
    }

    private val defaultKeys = "carName,alarms,addr"
    private val monitorKeys = "teamName,todayRun,driverSign,st1,st5,st2"
    private val modifyKeys = "driverStatic,alarms,addr,appDoor1,appDoor2,appDoor4"

    fun changeMode(mode: InfoMode) {
        when (mode) {
            InfoMode.DefaultMode -> changeListByKeys(defaultKeys)
            InfoMode.MonitorMode -> changeListByKeys(monitorKeys)
            InfoMode.ModifyMode -> changeListByKeys(modifyKeys)
        }
    }

    private fun changeListByKeys(keys: String) {
        changeList.forEach {
            it.switch = if (keys.contains(it.key)) 1 else 0
        }
        switchs.clear()
        switchs.addAll(changeList.filter { it.switch == 1 })
    }

    fun isModelOK(mode: InfoMode): Boolean {
        val isSet = InfoSetModel.isInfoSet(mode)
        if (isSet) {
            val had = when (mode) {
                InfoMode.DefaultMode -> isKey(defaultKeys) && switchs.size == 3
                InfoMode.MonitorMode -> isKey(monitorKeys) && switchs.size == 6
                InfoMode.ModifyMode -> isKey(modifyKeys) && switchs.size == 6
            }
            return had
        } else {
            return false
        }
    }

    //判断是否包含
    private fun isKey(keys: String): Boolean {
        for (switch in switchs) {
            if (!keys.contains(switch.key)) return false
        }
        return true
    }

    fun upData(data: GpsDetail?): ArrayList<LocationStatus> {
        switchList.clear()
        data?.run {
            switchs.forEach {
                val status = LocationStatus(it.key, it.switch)
                switchList.add(status)
                when (it.key) {
                    "drctCn" -> {
                        status.value = drctCn
                    }

                    "accTime" -> {
                        status.value = accTime
                    }

                    "teamName" -> {
                        status.value = teamName
                    }

                    "alarms" -> {
                        status.value = alarms ?: ""
                    }

                    "addr" -> {
                        status.value = addr ?: ""
                    }

                    "st1" -> {
                        status.value = getDesc(st1)
                    }

                    "st2" -> {
                        status.value = getDesc(st2)
                    }

                    "st3" -> {
                        status.value = getDesc(st3)
                    }

                    "st4" -> {
                        status.value = getDesc(st4)
                    }

                    "st5" -> {
                        status.value = getDesc(st5)
                    }

                    "carName" -> {
                        status.value = carName
                    }

                    "driverStatic" -> {
                        status.value =
                            if (drvName.isEmpty()) getString(R.string.desc_no_driver) else "$drvName:$drvPhone"
                    }

                    "driverSign" -> {
                        //小阮说不显示
                        status.value =
                            if (drvSign.isNullOrEmpty()) getString(R.string.desc_no_driver) else "$drvSign"
                    }

                    "satl" -> {
                        status.value = satl ?: ""
                    }

                    "sgn" -> {
                        status.value = sgn ?: ""
                    }
                    //前门的状态
                    "appDoor1" -> {
                        status.value = doorOpenClose(appDoor1)
                    }
                    //中门
                    "appDoor2" -> {
                        status.value = doorOpenClose(appDoor2)
                    }
                    //后门
                    "appDoor3" -> {
                        status.value = doorOpenClose(appDoor3)
                    }
                    //驾驶席门
                    "appDoor4" -> {
                        status.value = doorOpenClose(appDoor4)
                    }
                    //门5
                    "appDoor5" -> {
                        status.value = doorOpenClose(appDoor5)
                    }

                    "c3" -> {//{ "id": "c3", "name": "电量" }
                        val value = getExtsValue(exts, "c3")
                        status.value = value + if (value.isNotEmpty()) "%" else ""
                    }
                    //{ "id": "bd","name": "正反转状态" }
                    "bd" -> {
                        status.value = revState(getExtsValue(exts, "bd"))
                    }
                    //{ "id": "be","name": "正反转转速" }
                    "be" -> {
                        val value = getExtsValue(exts, "be")
                        status.value =
                            value + if (value.isNotEmpty()) AppContext.getDescById(R.string.unit_rev_min) else ""
                    }

                    "todayRun" -> {
                        status.value = TimeUtil.instance.formatTime(todayRun ?: 0)
                    }

                    "offlineDuration" -> {
                        status.value = offlineDuration ?: ""
                    }

                    "c4" -> {
                        val c4 = getExtsValue(exts, "c4")
                        if (c4.isEmpty()) {
                            status.value = ""
                        } else {
                            status.value = "$c4 ${getString(R.string.unit_voltage)}"
                        }
                    }

                    "tmnMile" -> {
                        status.value = (tmnMile ?: "") + " ${Units.km}"
                    }

                    "mileLng" -> {
                        val mileLng = getExtsValue(exts, "mileLng")
                        status.value = "$mileLng ${Units.km}"
                    }

                    "coiledDriving" -> {
                        status.value = "$coiledDriving"
                    }
                }
            }
            switchList.addAll(handProtocols(protocols))
        }

        return switchList
    }

    /**
     * 门开关
     *
     * @param state
     */
    private fun doorOpenClose(state: String?): String {
        return when (state) {
            "0" -> AppContext.getDescById(R.string.desc_door_close)
            "1" -> AppContext.getDescById(R.string.desc_door_open)
            else -> ""
        }
    }

    /**
     * 正反转状态转换
     *
     * @param type
     * @return
     */
    private fun revState(type: String): String {
        return when (type) {
            "00" -> AppContext.getDescById(R.string.desc_forward)
            "01" -> AppContext.getDescById(R.string.desc_reversal)
            "02" -> AppContext.getDescById(R.string.desc_stop)
            else -> ""
        }
    }

    fun getDesc(st: List<NameValue>?): String {
        var sensor = ""
        st?.forEach {
            sensor = "$sensor,${it.name}:${it.value}"
        }
        if (sensor.length > 1)
            sensor = sensor.substring(1)

        return sensor
    }

    /**
     * 通过key 获取描述
     */

    fun getDescByKey(key: String): Int {
        return when (key) {
            "drctCn" -> R.string.desc_run_drct
            "accTime" -> R.string.desc_acc_state
            "teamName" -> R.string.desc_belong_team
            "driverStatic" -> R.string.desc_driver_static
            "driverSign" -> R.string.desc_driver_sign
            "alarms" -> R.string.desc_now_alarm
            "addr" -> R.string.desc_com_address
            "st1" -> R.string.desc_oil_info
            "st3" -> R.string.desc_temp_info
            "st4" -> R.string.desc_damp_info
            "st5" -> R.string.desc_water_info
            "st2" -> R.string.desc_wight_info
            "carName" -> R.string.desc_offline_car_name
            "satl" -> R.string.desc_map_info_satl
            "sgn" -> R.string.desc_map_info_sgn
            "appDoor1" -> R.string.desc_door_0
            "appDoor2" -> R.string.desc_door_1
            "appDoor3" -> R.string.desc_door_2
            "appDoor4" -> R.string.desc_door_3
            "appDoor5" -> R.string.desc_door_4
            "c3" -> R.string.desc_map_info_elect
            "bd" -> R.string.desc_map_info_fwdRevState
            "be" -> R.string.desc_map_info_fwdRevSpeed
            "todayRun" -> R.string.desc_map_info_tody_run
            "offlineDuration" -> R.string.desc_offline_long
            "c4" -> R.string.desc_voltage
            "tmnMile" -> R.string.desc_tmn_mile
            "mileLng" -> R.string.desc_today_mile_lng
            "coiledDriving" -> R.string.desc_coiled_driving
            else -> R.string.desc_new_virsion
        }
    }


    /**
     * 通过key获取扩展内对应的数据
     *
     * @param json
     * @param key
     * @return
     */
    fun getExtsValue(json: String?, key: String): String {
        if (json.isNullOrEmpty()) return ""
        val jsonObject = JSONObject(json)
        val has = jsonObject.has(key)
        return if (has) {
            try {
                val value = jsonObject.get(key)
                value.toString()
            } catch (e: Exception) {
                ""
            }
        } else ""
    }

    /////////////////////////////// 自定义信息相关处理 ////////////////////////////////////////////////////////////
    private val mmKey = "${UserConstant.loginType}_locationInfo"
    val locations = ArrayList<LocationInfo>()

    /**
     * 处理数据
     *
     * @param infos
     */
    fun initLocations(infos: ArrayList<LocationInfo>) {
        thread {
            val oldInfos = CacheMMKV.decodeString(mmKey)
            var oldlocations = ArrayList<LocationInfo>()
            if (oldInfos.isNotEmpty()) {
                oldlocations = GsonUtil.formArrayList(oldInfos, LocationInfo::class.java)
            }
            var keys = ""
            infos.forEach {
                keys += ",${it.id}"
            }
            var oldKeys = ""
            val newLocations = ArrayList<LocationInfo>()
            for (location in oldlocations) {
                oldKeys += ",${location.id}"
                if (keys.contains(location.id)) {
                    newLocations.add(location)
                }
            }
            for (info in infos) {
                if (!oldKeys.contains(info.id)) newLocations.add(info)
            }
            newLocations.forEach {
                for (info in infos) {
                    if (it.id == info.id) {
                        it.kvs = info.kvs
                        it.unit = info.unit
                        it.verror = info.verror
                        it.vinvalid = info.vinvalid
                    }
                }
            }
            locations.clear()
            locations.addAll(newLocations)
        }
    }

    fun getLocationInfos() = locations

    /**
     * 保存自定义协议类型
     *
     * @param locations
     */
    fun saveLocations(locations: MutableList<LocationInfo>) {
        this.locations.clear()
        this.locations.addAll(locations)
        val toJson = GsonUtil.toJson(locations)
        CacheMMKV.encode(mmKey, toJson)
        LiveDataBus.get().with("upInfoState").postValue(true)
    }

    //处理自定义协议
    private fun handProtocols(protocols: String?): ArrayList<LocationStatus> {
        val extList = ArrayList<LocationStatus>()
        val formObject = GsonUtil.formObject<Map<String, Double>?>(protocols)
        locations.filter { it.switch == 1 }.forEach {
            val value = formObject?.get(it.id)
            val newValue =
                if (it.verror != null && it.verror == value) getString(R.string.desc_outlier)
                else if (it.vinvalid != null && it.vinvalid == value) getString(R.string.desc_invalid)
                else getNewValue(value, it.kvs, it.unit)
            extList.add(LocationStatus(it.id, it.switch, newValue, it.name))
        }
        return extList
    }

    /**
     * 获取新值
     *
     * @param value
     * @param kvs
     * @param unit
     * @return
     */
    private fun getNewValue(value: Double?, kvs: String?, unit: String?): String {
        val strV = value.toString()
        return if (kvs.isNullOrEmpty()) {
            if (unit.isNullOrEmpty()) {
                if (value == null) return ""
                strV

            } else {
                if (value == null) return ""
                "$value $unit"
            }
        } else {
            val map = GsonUtil.formObject<Map<String, String>>(kvs)
            val endsWith = strV.endsWith(".0")
            if (endsWith) {
                val key = value!!.toInt()
                map["$key"] ?: (map["other"] ?: "$strV $unit")
            } else {
                if (value == null) return ""
                map["other"] ?: "$strV $unit"
            }
        }
    }
}